package com.project.compiler;


import com.google.auto.service.AutoService;
import com.project.annotation.ARouterBean;
import com.project.annotation.Route;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;

@SupportedSourceVersion(SourceVersion.RELEASE_8)
//支持的注解类型
@SupportedAnnotationTypes({"com.project.annotation.Route"})

//用于从安卓项目里面传参过来
@SupportedOptions({Constant.MOUDLE_NAME,Constant.PACKAGE_NAME_FOR_APT})
@AutoService(Processor.class)
public class AppGroupAouteProcessor extends AbstractProcessor {

    //    类元素处理工具
    private Elements elementUtils;
    private Filer filer;    //文件生成器
    private Messager messager;      //日志打印工具
    private Types typeUtils;        //类属性处理工具
    private String moduleName;
    private String packageNameForApt;
    private Map<String,String> group = new HashMap<>();
    private Map<String, List<ARouterBean>> routerBeans = new HashMap<>();
    private Map<String,String> tempMap = new HashMap<>();


    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        elementUtils = processingEnvironment.getElementUtils();
        filer = processingEnvironment.getFiler();
        messager = processingEnvironment.getMessager();
        typeUtils = processingEnvironment.getTypeUtils();
        moduleName = processingEnvironment.getOptions().get(Constant.MOUDLE_NAME);
        packageNameForApt = processingEnvironment.getOptions().get(Constant.PACKAGE_NAME_FOR_APT);
        messager.printMessage(Diagnostic.Kind.NOTE,String.format("moduleName = %s, filePath = %s", moduleName, packageNameForApt));
        group.put(moduleName, packageNameForApt);
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {

        Set<? extends Element> elementSet = roundEnvironment.getElementsAnnotatedWith(Route.class);
        for (Element element:elementSet){
            if (element.getKind() != ElementKind.CLASS){
                throw new RuntimeException(String.format("only class can be annotation with %s,%s is not a class.",Route.class.getSimpleName(),element.getSimpleName()));
            }

//            遍历找到每个对应的注解类，然后做处理
            Route routeAnnotation = element.getAnnotation(Route.class);
            String path = routeAnnotation.path();
            String group = path.substring(path.indexOf("/")+1,path.indexOf("/",2));
            if (routerBeans.get(group) == null){
                routerBeans.put(group,new ArrayList<ARouterBean>());
            }
            ARouterBean routerBean = new ARouterBean.Builder()
                    .setGroup(group)
                    .setPath(path)
                    .setElement(element)
                    .build();
            routerBeans.get(group).add(routerBean);
        }
        //方法的返回值Map<String, RouterBean>
        TypeName typeName = ParameterizedTypeName.get(
                ClassName.get(Map.class),ClassName.get(String.class), ClassName.get(ARouterBean.class));
        for (Map.Entry<String,List<ARouterBean>> entry : routerBeans.entrySet()){
            //生成aRouterPath文件
//            Map<String, ARouterBean> map = new HashMap<>();
//            map.put("//",Bea);
            MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("getARouterPath")
                    .addAnnotation(Override.class)
                    .addModifiers(Modifier.PUBLIC)
                    .returns(typeName)
                    .addStatement("$T<$T,$T> $S = new $T<>()",ClassName.get(Map.class),
                            ClassName.get(String.class),ClassName.get(ARouterBean.class),"routerBeans",HashMap.class);
            List<ARouterBean> beans = entry.getValue();
            for (ARouterBean bean:beans){
                // pathMap.put("/order/Order_MainActivity",RouterBean.create(RouterBean.Type.ACTIVITY
                //        , Order_MainActivity.class,"/order/Order_MainActivity","order"));
                //因只能传基本类型，因此无法传非包装类的对象实例
                methodBuilder.addStatement("routerBeans.put($S,$T.create($T.$L,$T.class,$S,$S))",
                        bean.getPath(),
                        ClassName.get(ARouterBean.class),
                        ClassName.get(ARouterBean.Type.class),
                        bean.getType(),
                        ClassName.get((TypeElement) bean.getElement()),
                        bean.getPath(),
                        bean.getGroup());
            }
            methodBuilder.addStatement("return routerBeans");
            String finalClassName = group+"$Path$Router";
            messager.printMessage(Diagnostic.Kind.NOTE,"APT生成的group类为"+packageNameForApt+finalClassName);
            try {
                JavaFile.builder(packageNameForApt,
                        TypeSpec.classBuilder(finalClassName)
                                //该类实现的接口
                                .addSuperinterface(ClassName.get(elementUtils.getTypeElement("ARouterPath")))
                                .addModifiers(Modifier.PUBLIC)
                                //方法体
                                .addMethod(methodBuilder.build())
                                .build())
                        .build()
                        .writeTo(filer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            tempMap.put(entry.getKey(),finalClassName);

            creatGroupFile();
        }




        return true;
    }

    private void creatGroupFile() {
        //public Map<String, Class<? extends ARouterLoadPath>> loadGroup() {
        TypeName methodReturn = ParameterizedTypeName.get(ClassName.get(Map.class),ClassName.get(String.class)
                ,ParameterizedTypeName.get(ClassName.get(Class.class),
                        //Class<? extends ARouterLoadPath>
                        WildcardTypeName.subtypeOf(ClassName.get(elementUtils.getTypeElement("ARouterGroup")))));
        //方法体 public Map<String, RouterBean> loadPath() {}
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("getARouterGroup")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(methodReturn);
        //  Map<String, Class<? extends ARouterLoadPath>> groupMap = new HashMap<>();
        methodBuilder.addStatement("$T<$T,$T> $N = new $T<>()",
                ClassName.get(Map.class)
                ,ClassName.get(String.class),
                ParameterizedTypeName.get(ClassName.get(Class.class),
                        WildcardTypeName.subtypeOf(ClassName.get(elementUtils.getTypeElement("ARouterGroup")))),
                "group"
                ,HashMap.class);
        //groupMap.put("order",ARouter$$Path$$order.class);
        for (Map.Entry<String, String> entry : tempMap.entrySet()) {
            methodBuilder.addStatement("$N.put($S,$T.class)",
                    "group",
                    entry.getKey(),
                    //指定的包名下
                    ClassName.get(packageNameForApt,entry.getValue()));
        }
        methodBuilder.addStatement("return $N","group");
        String finalClassName = "$Group$" + moduleName;
        messager.printMessage(Diagnostic.Kind.NOTE,
                "APT生成的group类为"+packageNameForApt+finalClassName);
        try {
            JavaFile.builder(packageNameForApt,
                    TypeSpec.classBuilder(finalClassName)
                            //该类实现的接口
                            .addSuperinterface(ClassName.get(elementUtils.getTypeElement("ARouterGroup")))
                            .addModifiers(Modifier.PUBLIC)
                            //方法体
                            .addMethod(methodBuilder.build())
                            .build())
                    .build()
                    .writeTo(filer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
//支持的Java版本
